package online.flytool.base.refect;

import online.flytool.base.check.Assert;

import java.util.IdentityHashMap;
import java.util.Map;

public class ClassUtils {


    /**
     * 包装类映射到原始类型
     */
    private static final Map<Class<?>, Class<?>> wrapperToPrimitiveTypeMap = new IdentityHashMap<>(8);

    /**
     * 原始类型映射到包装类
     */
    private static final Map<Class<?>, Class<?>> primitiveTypeToWrapperMap = new IdentityHashMap<>(8);

    static {
        //  初始化基本数据类型与对应的保证类的映射
        wrapperToPrimitiveTypeMap.put(Boolean.class, boolean.class);
        wrapperToPrimitiveTypeMap.put(Byte.class, byte.class);
        wrapperToPrimitiveTypeMap.put(Character.class, char.class);
        wrapperToPrimitiveTypeMap.put(Double.class, double.class);
        wrapperToPrimitiveTypeMap.put(Float.class, float.class);
        wrapperToPrimitiveTypeMap.put(Integer.class, int.class);
        wrapperToPrimitiveTypeMap.put(Long.class, long.class);
        wrapperToPrimitiveTypeMap.put(Short.class, short.class);

        for (Map.Entry<Class<?>, Class<?>> entry : wrapperToPrimitiveTypeMap.entrySet()) {
            primitiveTypeToWrapperMap.put(entry.getValue(), entry.getKey());
        }

    }

    /**
     * 幸运的是，forName()方法提供了重载方法，其接收一个类加载器，以及是否执行类初始化两个参数。根据文档，下面调用时等价的：
     * @param str
     * @return
     */
    public static boolean exist(String str){
        try {
            Class.forName(str,false,ClassUtils.class.getClassLoader());
            return true;
        } catch (ClassNotFoundException e) {
            //throw new RuntimeException(e);
            return false;
        }
    }

    /**
     * 是否可以访问
     * @param lhsType
     * @param rhsType
     * @return
     */
    public static boolean isAssignable(Class<?> lhsType, Class<?> rhsType) {
        Assert.notNull(lhsType, "Left-hand side type must not be null");
        Assert.notNull(rhsType, "Right-hand side type must not be null");
        // 若左边类型 是右边类型的父类、父接口，或者左边类型等于右边类型
        if (lhsType.isAssignableFrom(rhsType)) {
            return true;
        }
        // 左边入参是否是基本类型
        if (lhsType.isPrimitive()) {
            //primitiveWrapperTypeMap是从包装类型到基本类型的map，将右边入参转化为基本类型
            Class<?> resolvedPrimitive = wrapperToPrimitiveTypeMap.get(rhsType);
            if (lhsType == resolvedPrimitive) {
                return true;
            }
        }
        else {
            // 将右边入参转化为包装类型
            Class<?> resolvedWrapper = primitiveTypeToWrapperMap.get(rhsType);
            if (resolvedWrapper != null && lhsType.isAssignableFrom(resolvedWrapper))
            {
                return true;
            }
        }
        return false;
    }



}
